#include "stepper.h"
#include <QDebug>
#include <QApplication>
#ifdef ARM32
  #include <termios.h>
  #include <fcntl.h>
  #include <sys/ioctl.h>
  #include <unistd.h>
#endif
CStepper s;

CStepper::CStepper()
{
  dstep = 1;
  speed = 7;
  mx = my = mz = 400;
  load();
}
CStepper::~CStepper()
{
  deload();
}

void CStepper::load()
{
#ifdef ARM32
  MyDriver = open("/dev/heval", 0);
#endif
}
void CStepper::deload()
{
#ifdef ARM32
  close(MyDriver);
#endif
}

void CStepper::exec()
{
/*  bool dirx = x > 0;
  bool diry = y > 0;
  bool dirz = z > 0;
  bool dirzchanged = false;
  set(DX, dirx);
  set(DY, diry);
  set(DZ, dirz);
  int cx = 0, cy = 0, cz = 0;
  int bx = x;
  int a0 = TX, a1 = TY, a2 = TZ;
  if(abs(y) > abs(z) && abs(y) > abs(x))
  {
    x = y;
    y = bx;
    a0 = TY;
    a1 = TX;
  }

  if(abs(z) > abs(y) && abs(z) > abs(x))
  {
    x = z;
    z = bx;
    a0 = TZ;
    a2 = TX;
  }

  int dx =  abs(x), sx = cx<x ? 1 : -1;
  int dy = -abs(y), sy = cy<y ? 1 : -1;
  int dz = -abs(z), sz = cz<z ? 1 : -1;
  int e_xy = dx+dy, e2y;
  int e_xz = dx+dz, e2z;
  while(free())
  {
    if(cx==x && cy == y && cz == z) break;
    e2y = 2*e_xy;
    e2z = 2*e_xz;
    if (e2y >= dy) { e_xy += dy; e_xz += dz; cx += sx; step(a0);}
    if (e2y <= dx) { e_xy += dx; cy += sy; step(a1);}
    if (e2z <= dx) { e_xz += dx; cz += sz; step(a2);}
    if(cx==0 && cy == 0 && cz == 0) break;
    while(keys.contains(KEY_PAUSE) || state == PAUSE )
    {
      qApp->processEvents();
      if(state == CANCELED)
        return;
    }
    if(keys.contains(KEY_REV))
    {
      set(DX, !dirx);
      set(DY, !diry);
      set(DZ, !dirz);
      if(state == PLOTTING) state = REVERTING;
      if(state == REVERTING) state = PLOTTING;
    }
    while(ckeys.contains(104) || ckeys.contains(109))
    {
      set(DZ, ckeys.indexOf(104) <  ckeys.indexOf(109));
      dirzchanged = true;
      step(TZ);
    }
    if(dirzchanged)
    {
      set(DZ,dirz);
      dirzchanged = false;
    }
    if(ckeys.contains(1) ||  state == CANCELED || state == STANDBY)
      return;
  }*/
}

void CStepper::pause()
{
  for(int i=0; i < speed*1000; i++)
    ;
}

bool CStepper::free()
{
  reades();
  if(es[0] == AN) return false;
  if(es[1] == AN) return false;
  if(es[2] == AN) return false;
  return true;
}

void CStepper::set(int p, int v)
{
#ifdef ARM32
  ioctl(MyDriver, v, p);
  if(p == DX || p == DY || p == DZ)
    cd[p-DX]=v;
#endif
}
void CStepper::reades()
{
#ifdef ARM32
  read(MyDriver, es, sizeof(es));
#endif
}

void timer_handler (int signum)
{
  qDebug() << "timer" << signum;
}

void CStepper::reset()
{ 
  /*struct sigaction sa;
  struct itimerval timer;

  memset (&sa, 0, sizeof (sa));
  sa.sa_handler = &timer_handler;
  sigaction (SIGVTALRM, &sa, NULL);

  timer.it_value.tv_sec = 0;
  timer.it_value.tv_usec = 0;

  timer.it_interval.tv_sec = 0;
  timer.it_interval.tv_usec = 250000;

  setitimer (ITIMER_VIRTUAL, &timer, NULL);*/
#ifdef ARM32
  set(DX, 0);
  set(DY, 0);
  set(DZ, 0);
  es[0] = AUS;
  es[1] = AUS;
  es[2] = AUS;
  k.start();
  while(es[0] == 0x30 || es[1] == 0x30 || es[2] == 0x30 )
  {
    reades();
    if(es[0]== AUS) set(TX, 1);
    if(es[1]== AUS) set(TY, 1);
    if(es[2]== AUS) set(TZ, 1);
    pause();
    if(es[0]== AUS) set(TX, 0);
    if(es[1]== AUS) set(TY, 0);
    if(es[2]== AUS) set(TZ, 0);
    pause();
    while(keys.contains(KEY_P) || state == PAUSE )
    {
      qApp->processEvents();
    }
  }
  set(DX, 1);
  set(DY, 1);
  set(DZ, 1);
  for(int i =0; i < 200; i++)
  {
    set(TX, 1);
    set(TY, 1);
    set(TZ, 1);
    pause();
    set(TX, 0);
    set(TY, 0);
    set(TZ, 0);
    pause();
  }
  c[0] = 0;
  c[1] = 0;
  c[2] = 0;
  k.terminate();
  emit terminated();
#endif
}

void CStepper::step(int ia)
{
  c[ia] += cd[ia]*2-1;
  set(ia,1);
  pause();
  set(ia,0);
  pause();
}

void CStepper::line(int vx, int vy, int vz)
{
#ifdef ARM32
  if(vx==0 && vy == 0 && vz == 0) return;
  x = vx;
  y = vy;
  z = vz;
  bool dirz = z > 0;
  bool dirzchanged = false;
  set(DX, x > 0);
  set(DY, y > 0);
  set(DZ, z > 0);
  int cx = 0, cy = 0, cz = 0;
  int bx = x;
  int a0 = TX, a1 = TY, a2 = TZ;
  if(abs(y) > abs(z) && abs(y) > abs(x))
  {
    x = y;
    y = bx;
    a0 = TY;
    a1 = TX;
  }

  if(abs(z) > abs(y) && abs(z) > abs(x))
  {
    x = z;
    z = bx;
    a0 = TZ;
    a2 = TX;
  }

  int dx =  abs(x), sx = cx<x ? 1 : -1;
  int dy = -abs(y), sy = cy<y ? 1 : -1;
  int dz = -abs(z), sz = cz<z ? 1 : -1;
  int e_xy = dx+dy, e2y;
  int e_xz = dx+dz, e2z;
  while(free())
  {
    if(cx==x && cy == y && cz == z) break;
    e2y = 2*e_xy;
    e2z = 2*e_xz;
    if (e2y >= dy) { e_xy += dy; e_xz += dz; cx += sx; step(a0);}
    if (e2y <= dx) { e_xy += dx; cy += sy; step(a1);}
    if (e2z <= dx) { e_xz += dx; cz += sz; step(a2);}
    while(keys.contains(KEY_P) || state == PAUSE )
    {
      qApp->processEvents();
      if(state == CANCELED)
        return;
    }
    while(ckeys.contains(KEY_PAGEUP) || ckeys.contains(KEY_PAGEDOWN))
    {
      set(DZ, ckeys.indexOf(KEY_PAGEUP) <  ckeys.indexOf(KEY_PAGEDOWN));
      dirzchanged = true;
      step(TZ);
    }
    if(dirzchanged)
    {
      set(DZ,dirz);
      dirzchanged = false;
    }
    if(ckeys.contains(1) ||  state == CANCELED || state == STANDBY)
      return;
  }
#endif
}

void CStepper::run()
{
  exec();
}

